package com.hanxiaozhang.bigflie;

import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.util.Optional;


@RequestMapping("/download")
@RestController
@Slf4j
public class DownLoadController {

    private final static String utf8 = "utf-8";

    @GetMapping("/file")
    public void downLoadFile(HttpServletRequest request, HttpServletResponse response) throws IOException {
        // 设置编码格式
        response.setCharacterEncoding(utf8);
        //获取文件路径
        String drive = "E";
        String fileName = "test1.zip";
        //参数校验

        log.info(fileName, drive);
        //完整路径(路径拼接待优化-前端传输优化-后端从新格式化  )
        String pathAll = drive + ":\\" + fileName;
        log.info("pathAll{}", pathAll);
        Optional<String> pathFlag = Optional.ofNullable(pathAll);
        File file = null;
        if (pathFlag.isPresent()) {
            //根据文件名，读取file流
            file = new File(pathAll);
            log.info("文件路径是{}", pathAll);
            if (!file.exists()) {
                log.warn("文件不存在");
                return;
            }
        } else {
            //请输入文件名
            log.warn("请输入文件名！");
            return;
        }

        InputStream is = null;
        OutputStream os = null;
        try {
            //获取长度
            long fSize = file.length();
            response.setContentType("application/x-download");
            String file_Name = URLEncoder.encode(file.getName(), "UTF-8");
            response.addHeader("Content-Disposition", "attachment;filename=" + fileName);
            //根据前端传来的Range  判断支不支持分片下载
            response.setHeader("Accept-Range", "bytes");
            // response.setHeader("fSize",String.valueOf(fSize))
            response.setHeader("fName", file_Name);
            //定义断点
            long pos = 0, last = fSize - 1, sum = 0;
            //判断前端需不需要分片下载
            if (null != request.getHeader("Range")) {
                response.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT);
                String numRange = request.getHeader("Range").replaceAll("bytes=", "");
                String[] strRange = numRange.split("-");
                if (strRange.length == 2) {
                    pos = Long.parseLong(strRange[0].trim());
                    last = Long.parseLong(strRange[1].trim());

                    if (pos == 83886080L) {
                        throw new RuntimeException("22");
                    }
                    //若结束字节超出文件大小 取文件大小
                    if (last > fSize - 1) {
                        last = fSize - 1;
                    }
                } else {
                    //若只给一个长度  开始位置一直到结束
                    pos = Long.parseLong(numRange.replaceAll("-", "").trim());
                }
            }
            long rangeLenght = last - pos + 1;
            String contentRange = new StringBuffer("bytes").append(pos).append("-").append(last).append("/").append(fSize).toString();
            response.setHeader("Content-Range", contentRange);
            os = new BufferedOutputStream(response.getOutputStream());
            is = new BufferedInputStream(new FileInputStream(file));
            //跳过已读的文件(重点，跳过之前已经读过的文件)
            is.skip(pos);
            byte[] buffer = new byte[1024];
            int lenght = 0;
            //相等证明读完
            while (sum < rangeLenght) {
                lenght = is.read(buffer, 0, (rangeLenght - sum) <= buffer.length ? (int) (rangeLenght - sum) : buffer.length);
                sum = sum + lenght;
                os.write(buffer, 0, lenght);
            }
            log.info("下载完成");
        } finally {
            if (is != null) {
                is.close();
            }
            if (os != null) {
                os.close();
            }
        }
    }
}